package cn.javass.framework.web.config;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.javass.framework.aop.annotation.IInterceptor;
import cn.javass.framework.aop.interceptor.Interceptor;
import cn.javass.framework.web.annotation.IAction;
import cn.javass.framework.web.annotation.IGoto;

public class Configuration {
	private static Configuration cfg = null;
	private static Map<String, ActionMapper> actionMapper = new HashMap<String, ActionMapper>();

	public static Configuration configure() {
		return configure(null);
	}
	
	public static Configuration configure(String root) {
		if (cfg == null) {
			synchronized (Configuration.class) {
				cfg = new Configuration();
				cfg.builder(root);
			}
		}
		return cfg;
	}

	private void builder(String rootStr) {
		if(rootStr==null){
			rootStr = getClass().getClassLoader().getResource(".").getPath().substring(1);
		}
		File root = new File(rootStr);
		parse(root, rootStr.length());
	}

	private void parse(File root, int length) {
		if (root.isDirectory()) {
			for (File file : root.listFiles()) {
				parse(file, length);
			}
		} else {

			if (root.getName().endsWith(".class")) {

				String clazzName = root.getAbsolutePath();
				clazzName = clazzName.substring(length, clazzName.length() - 6)
						.replace(File.separatorChar, '.');
				processAnnotation(clazzName);
			}
		}
	}

	private void processAnnotation(String clazzName) {
		try {
			Class clazz = Class.forName(clazzName);
			if (clazz.isAnnotationPresent(IAction.class)) {
				makeActionMapper(clazz);
			}
		} catch (Throwable e) {
		}
	}

	private void makeActionMapper(Class clazz) throws Exception {
		ActionMapper am = new ActionMapper();
		IAction actionAnnotation = (IAction) clazz.getAnnotation(IAction.class);
		am.setActionClass(clazz);
		am.setPath(actionAnnotation.path());
		makeGoto(actionAnnotation.result(),am);
		if(clazz.isAnnotationPresent(IInterceptor.class)){
			am.setInterceptors(makeInteceptors((IInterceptor)clazz.getAnnotation(IInterceptor.class)));
		}
		actionMapper.put(am.getPath(), am);

		
	}
	
	private List<Interceptor> makeInteceptors(IInterceptor interceptorAnnotation){
		List<Interceptor> interceptors = new ArrayList<Interceptor>();
		for(Class clazz:interceptorAnnotation.classes()){
			try {
				interceptors.add((Interceptor) clazz.newInstance());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return interceptors;
	}

	private void makeGoto(IGoto[] gotos,ActionMapper am) {
		for(IGoto to: gotos){
			if("".equals(to.key()) || "".equals(to.path())){
			  continue;	
			}
			
			am.getGotos().put(to.key(), to.path());
		}
	}

	public static ActionMapper getActionMapper(String path){
		return actionMapper.get(path);
	}
	
	public static void main(String[] args) throws Exception {
		Configuration.configure();
		System.out.println(Configuration.actionMapper.get("/test").getActionClass());
	}

}
